package com.aygxy.carproject.service.impl;

import com.aygxy.carproject.ex.ServiceCode;
import com.aygxy.carproject.ex.ServiceException;
import com.aygxy.carproject.pojo.category.entity.CategoryTreeEntity;
import com.aygxy.carproject.pojo.category.vo.CategoryStandardVO;
import com.aygxy.carproject.pojo.category.vo.CategoryTreeVO;
import com.aygxy.carproject.service.CategoryService;
import com.aygxy.carproject.service.CategoryTreeService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Service
@Slf4j
public class CategoryTreeServiceImpl implements CategoryTreeService {
    @Autowired
    private CategoryService categoryService;
    @Override
    public CategoryTreeVO categoryTree() {
        List<CategoryStandardVO> categoryStandardVOs=
                categoryService.getCategoryList();
        CategoryTreeVO<CategoryTreeEntity> treeVO=
                initTree(categoryStandardVOs);
        return treeVO;
    }



    // 将从数据库中查询到的分类对象转换为三级分类树的方法
    private CategoryTreeVO<CategoryTreeEntity> initTree(
            List<CategoryStandardVO> categoryStandardVOs) {
        // 第一步:
        // 确实所有分类对象的父分类id
        // 以父分类id为key,将相同父分类的子分类对象保存到同一个Map的key中
        // 一个父分类可能包含多个子分类,所有这个Map的value是一个List
        Map<Long,List<CategoryTreeEntity>> map=new HashMap<>();
        log.info("当前分类对象总数:{}",categoryStandardVOs.size());
        // 遍历所有分类对象的集合
        for(CategoryStandardVO categoryStandardVO: categoryStandardVOs){
            // CategoryStandardVO是没有children熟悉的不能保存分类父子关系
            // 所有我们要先将其中的对象转换为能够保存父子分类关系的FrontCategoryEntity
            CategoryTreeEntity CategoryTreeEntity=new CategoryTreeEntity();
            // 将同名属性赋值到frontCategoryEntity对象中
            BeanUtils.copyProperties(categoryStandardVO,CategoryTreeEntity);
            // 获取当前元素对应的父分类id(父分类id为0表示当前分类对象为一级分类)
            // 后面反复使用这个父分类id,所以最好取出
            Long parentId=CategoryTreeEntity.getParentId();
            // 这个父分类id要作为key保存到map中,所有要先判断map中是否已经包含这个key
            if(map.containsKey(parentId)){
                // 运行到这表示当前map已经包含了这个父分类的key
                // 将当前分类追加到map元素的value中
                map.get(parentId).add(CategoryTreeEntity);
            }else {
                // 运行到这表示当前map还没有这个父分类id的key对应的元素
                // 先实例化一个list对象当做map的value,并添加当前分类对象
                List<CategoryTreeEntity> value=new ArrayList<>();
                value.add(CategoryTreeEntity);
                // 在map中创建一个以父分类id为key的元素(使用put方法)
                map.put(parentId,value);
            }
        }
        // 第二步:
        // 将子分类对象关联到父分类对象的children属性中
        // 下面操作应该从一级分类开始,我们先通过0作为父分类id获得所有一级分类
        List<CategoryTreeEntity> firstLevels=map.get(0L);
        // 判断一级分类集合是否为空,防止后续出现空指针
        if(firstLevels==null || firstLevels.isEmpty()){
            throw new ServiceException(
                    ServiceCode.INTERNAL_SERVER_ERROR,"没有一级分类,运行结束");
        }
        // 遍历所有一级分类对象
        for(CategoryTreeEntity oneLevel : firstLevels){
            // 获得当前一级分类的id
            Long secondLevelParentId=oneLevel.getId();
            // 获取当前一级分类对象包含的二级分类集合
            List<CategoryTreeEntity> secondLevels=map.get(secondLevelParentId);
            if(secondLevels==null || secondLevels.isEmpty()){
                log.warn("当前分类没有二级分类内容:{}",secondLevelParentId);
                // 如果当前一级分类没有二级分类,跳过本次循环,继续下次循环
                continue;
            }
            // 遍历二级分类对象集合
            for(CategoryTreeEntity twoLevel : secondLevels){
                // 获得二级分类的id(三级分类的父id)
                //                               ↓↓↓↓↓↓
                Long thirdLevelParentId=twoLevel.getId();
                // 根据二级分类id获得对应当前二级分类对象的所有三级分类元素集合
                List<CategoryTreeEntity> thirdLevels=map.get(thirdLevelParentId);
                // 判断当前三级分类是否为空
                if(thirdLevels==null || thirdLevels.isEmpty()){
                    log.warn("当前二级分类对象没有三级分类内容:{}",thirdLevelParentId);
                    continue;
                }
                // 将三级分类对象集合,保存到二级分类对象的children属性中
                twoLevel.setChildrens(thirdLevels);
            }
            // 将二级分类对象集合,保存到一级分类对象的children属性中
            oneLevel.setChildrens(secondLevels);
        }
        // 到此为止,所有的分类对象都保存到了正确的父分类对象的children属性中
        // 最终包含它们的是firstLevels集合,但是我们的返回值是FrontCategoryTreeVO<FrontCategoryEntity>
        // 所以我们要实例化这个类型对象,并将firstLevels赋值到其中,然后返回
        CategoryTreeVO<CategoryTreeEntity> treeVO=
                new CategoryTreeVO<>();
        treeVO.setCategories(firstLevels);
        // 千万记得返回treeVO对象!!!!
        return treeVO;
    }
}
